﻿using System;
using System.Linq;
using System.Web.UI;
using System.Web.UI.WebControls.WebParts;

namespace Synergy.Web.UI.WebControls.WebParts
{
	/// <summary>
	/// Base class for a <see cref="WebPart"/> that automatically loads a user control based on the applied <see cref="UserControlAttribute"/>.
	/// </summary>
	/// <remarks>
	///		<list type="table">
	///			<listheader><term>Version</term><description>Description</description></listheader>
	///			<item>
	///				<term>1.0</term>
	///				<description>Initial version</description>
	///			</item>
	///		</list>
	/// </remarks>
	public class UserControlWebPart : WebPart
	{
		#region | Fields |

		/// <summary>Error message format to display if there is a load error. Params: {0} virtual path; {1} exception message.</summary>
		private const string ErrorMessageFormat = @"The <b>{0}</b> control failed to load: <span style=""color:#f00;font-style:italic"">{1}</span>";

		#endregion

        
		#region | Initialization |

        /// <summary>
        /// Initializes a new instance of the <see cref="UserControlWebPart&lt;TWebPart&gt;"/> class.
        /// </summary>
        public UserControlWebPart()
		{
			Init += UserControlWebPart_Init;
		}

		#endregion


		#region | Properties |

		/// <summary>
		/// Gets or sets the content control.
		/// </summary>
		/// <value>The content control.</value>
		public Control ContentControl { get; private set; }

		#endregion


		#region | Methods [Private] |

		/// <summary>
		/// Clears the content control.
		/// </summary>
		private void ClearContentControl()
		{
			// if there is no content control, there's nothing to do
			if (ContentControl == null)
			{
				return;
			}

			// if control is an IWebPartContentControl, reset its WebPart property
			var control = ContentControl as IWebPartContentControl;
			if (control != null)
			{
			    control.WebPart = null;
			}

			// remove the control
			Controls.Remove(ContentControl);
		}


		/// <summary>
		/// Loads the control from user control attribute.
		/// </summary>
		private void LoadControlFromUserControlAttribute()
		{
			// grab the first UserControlAttribute; return if none is found
			var attribute = (from a in GetType().GetCustomAttributes(typeof(UserControlAttribute), true)
							 select a).First() as UserControlAttribute;
			if (attribute == null)
			{
				return;
			}
			
			// clear any existing content
			ClearContentControl();

			// load control
			try
			{
				// load control
				var control = Page.LoadControl(attribute.VirtualPath);
				
				// if control is an IWebPartContentControl, set WebPart property
				var contentControl = control as IWebPartContentControl;
				if (contentControl != null)
				{
					contentControl.WebPart = this;
				}

				// add control
				ContentControl = control;
				Controls.Add(ContentControl);
			}
			catch (Exception exception)
			{
				// control failed to load; show error
				Controls.Add(new LiteralControl(string.Format(ErrorMessageFormat, attribute.VirtualPath, exception.Message)));
			}
		}


		/// <summary>
		/// Handles the Init event of the UserControlWebPart control.
		/// </summary>
		/// <param name="sender">The source of the event.</param>
		/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
		private void UserControlWebPart_Init(object sender, EventArgs e)
		{
			LoadControlFromUserControlAttribute();
		}

		#endregion
	}
}